var express = require("express");
var router = express.Router();
const multiparty = require("multiparty");
const path = require("path");
const fse = require("fs-extra");

const UPLOAD_DIR = path.resolve(__dirname, "../", "upload");

// 提取文件后缀名
const extracExt = (filename) => {
  return filename.slice(filename.lastIndexOf("."), filename.length);
};

/* GET home page. */
router.get("/", function (req, res, next) {
  res.render("index", { title: "Express" });
});

router.post("/upload", (req, res) => {
  const form = new multiparty.Form();
  form.parse(req, async (err, fields, files) => {
    if (err) {
      console.log(err);
      res.send({
        code: 401,
        msg: "上传失败,重试",
      });
      return;
    }

    const fileHash = fields["fileHash"] ? fields["fileHash"][0] : null;
    const chunkHash = fields["chunkHash"] ? fields["chunkHash"][0] : null;

    if (files["file"]) { // 上传的是单个文件
      const file = files["file"][0];
      const filePath = path.resolve(UPLOAD_DIR, file.originalFilename);
      try {
        await fse.move(file.path, filePath);
        res.send({
          code: 200,
          msg: "文件上传成功",
        });
      } catch (error) {
        console.log(error);
        res.send({
          code: 401,
          msg: "文件上传失败,重试",
        });
      }
    } else if (files["chunk"]) { // 上传的是文件切片
      if (!fileHash || !chunkHash) {
        res.send({
          code: 400,
          msg: "缺少必要的字段",
        });
        return;
      }

      // 创建临时目录
      const chunkPath = path.resolve(UPLOAD_DIR, fileHash);

      if (!fse.existsSync(chunkPath)) {
        fse.mkdirSync(chunkPath);
      }

      const oldPath = files["chunk"][0].path;

      // 将切片放到文件夹当中
      fse.move(oldPath, path.resolve(chunkPath, chunkHash))
        .then(() => {
          res.send({
            code: 200,
            msg: "切片上传成功",
          });
        })
        .catch((error) => {
          console.log(error);
          res.send({
            code: 401,
            msg: "切片上传失败,重试",
          });
        });
    } else {
      res.send({
        code: 400,
        msg: "上传内容不支持",
      });
    }
  });
});

router.post("/merge", async (req, res) => {
  const { fileHash, fileName, size } = req.body;

  const filePath = path.resolve(UPLOAD_DIR, fileHash + extracExt(fileName));

  if (fse.existsSync(filePath)) {
    res.send({
      code: 200,
      msg: "文件已存在",
    });
    return;
  }

  const chunkDir = path.resolve(UPLOAD_DIR, fileHash);
  if (!fse.existsSync(chunkDir)) {
    res.send({
      code: 401,
      msg: "合并失败,重新上传",
    });
    return;
  }

  const chunkPaths = await fse.readdir(chunkDir);

  chunkPaths.sort((a, b) => {
    return a.split("-")[1] - b.split("-")[1];
  });

  const list = chunkPaths.map((chunkName, index) => {
    return new Promise((resolve, reject) => {
      const chunkPath = path.resolve(chunkDir, chunkName);
      const readStream = fse.createReadStream(chunkPath);
      const writeStream = fse.createWriteStream(filePath, {
        start: index * size,
        end: (index + 1) * size,
      });
      readStream.on("end", () => {
        fse.unlinkSync(chunkPath);
        resolve();
      });
      readStream.pipe(writeStream);
    });
  });

  await Promise.all(list);
  await fse.remove(chunkDir);

  res.send({
    code: 200,
    msg: "文件合并成功",
  });
});

router.post('/verify', async (req, res) => {
  const { fileHash, fileName } = req.body;

  const filePath = path.resolve(UPLOAD_DIR, fileHash + extracExt(fileName));

  const chunkDir = path.resolve(UPLOAD_DIR, fileHash);
  let chunkPaths = [];
  if (fse.existsSync(chunkDir)) {
    chunkPaths = await fse.readdir(chunkDir);
  }

  if (fse.existsSync(filePath)) {
    res.send({
      code: 200,
      msg: "文件已存在",
      data: {
        shouldUpload: false,
        existChunks: chunkPaths,
      },
    });
  } else {
    res.send({
      code: 200,
      msg: "文件不存在",
      data: {
        shouldUpload: true,
        existChunks: chunkPaths,
      },
    });
  }
});

module.exports = router;
